#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct Node {
    char data;
    struct Node *next;
} Node;

void remove_by_count(Node **list, size_t n)
{
    if (*list != NULL)
    {
        Node *sublist = (*list)->next;
        if (n == 1)
        {
            free(*list);
            *list = sublist;
        }
        else
        {
            remove_by_count(&(*list)->next, n - 1);
        }
    }
}

size_t remove_by_count_backward(Node **list, size_t n)
{
    if (*list == NULL)
    {
        return 0;
    }
    else
    {
        size_t count = 1 + remove_by_count_backward(&(*list)->next, n);
        if (count == n)
        {
            Node *head = *list;
            *list = head->next;
            free(head);
        }
        return count;
    }
}

void print_list(Node * node)
{
    if (node != NULL)
    {
        printf("%c", node->data);
        if (node->next != NULL)
        {
            printf("->");
            print_list(node->next);
        }
        else
        {
            printf("\n");
        }
    }
}

size_t count_list_impl(Node *list, size_t count)
{
    return (NULL == list)?count:count_list_impl(list->next, count + 1);
}

size_t count_list(Node *list)
{
    return (list == NULL)? 0 : count_list_impl(list, 0);
}

Node *add_node(Node **list, Node *node)
{
    if (*list == NULL)
    {
        *list = node;
    }
    else
    {
        add_node(&(*list)->next, node);
    }
    return *list;
}

Node * new_node(char c)
{
    Node *node = calloc(1, sizeof(Node));
    node->data = c;
    return node;
}

Node * list_init_from_stdin(void)
{
    Node *list = NULL;
    int c = getchar();
    while (c != EOF)
    {
        if (isgraph(c))
        {
            add_node(&list, new_node(c));
        }
        c = getchar();
    }

    return list;
}

void print_count(Node *list)
{
    int i = 1;
    while (list != NULL)
    {
        printf("[%c(%d)] ", list->data, i);
        list=list->next;
        i++;
    }
}

size_t print_count_backward(Node *list)
{
    if (NULL == list)
    {
        return 0;
    }
    else
    {
        size_t backward_count = 1 + print_count_backward(list->next);
        printf("[%c(%zd)] ", list->data, backward_count);
        return backward_count;
    }
}

void release_list(Node *node)
{
    if (node == NULL)
    {
        return;
    }
    if (node->next != NULL)
    {
        release_list(node->next);
    }

    free(node);
}

int main(int argc, const char *argv[])
{
    printf("input some characters to init a list. ( EOF (ctr + z) on windows or (ctr + d) on *nix) to finish input)\n");
    Node *list = list_init_from_stdin();

    printf("\n");
    print_list(list);

    if (NULL != list)
    {
        rewind(stdin);
        printf("\nchoose one number to remove [1..%zd]:\n", count_list(list));
        print_count(list);
        printf("\n");
        int c=0;
        scanf("%d", &c);
        remove_by_count(&list, c);
    }

    print_list(list);

    if (NULL != list)
    {
        rewind(stdin);
        printf("\nchoose one number count from bottom to remove [1..%zd]:\n", count_list(list));
        print_count_backward(list);
        printf("\n");

        int c=0;
        scanf("%d", &c);

        remove_by_count_backward(&list, c);
    }

    print_list(list);

    release_list(list);
    
    return 0;
}
